{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8d3c680b",
   "metadata": {},
   "source": [
    "# 线性代数模块\n",
    "\n",
    "scipy.linalg是SciPy中负责线性代数计算的模块。NumPy也有numpy.linalg模块，不过建议使用scipy.linalg，原因有二：\n",
    "- scipy.linalg包含numpy.linalg中的所有函数，同时还包含了很多numpy.linalg中没有的函数；\n",
    "- scipy.linalg默认使用线性代数库BLAS/LAPACK等对运算进行加速，而在numpy.linalg中，这些加速是需要自己配置，不是默认设置:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "aa0ef52c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy.linalg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1cba1a1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import scipy.linalg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b65ef6f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "34"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(dir(numpy.linalg))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4a139a95",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "156"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(dir(scipy.linalg))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c920896b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "571cb2e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy import linalg"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79b71214",
   "metadata": {},
   "source": [
    "## 基本的矩阵操作"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "969794d4",
   "metadata": {},
   "source": [
    "在NumPy中，矩阵有两种表示方法：矩阵类型和二维数组类型。\n",
    "\n",
    "矩阵类型可以用`np.mat()`或者`np.matrix()`创建："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "fa1f33c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.mat(\"[1, 2; 3, 4]\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "094e37a6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 2],\n",
       "        [3, 4]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d221a93a",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.matrix(\"[1, 2; 3, 4]\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ffb1da83",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 2],\n",
       "        [3, 4]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "2e135a8f",
   "metadata": {},
   "source": [
    "转置矩阵为："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5544773c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 3],\n",
       "        [2, 4]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.T"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "755aa7fa",
   "metadata": {},
   "source": [
    "矩阵的逆矩阵："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d895134e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[-2. ,  1. ],\n",
       "        [ 1.5, -0.5]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.I"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e19f8bcc",
   "metadata": {},
   "source": [
    "矩阵乘法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "4a6607e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1.00000000e+00, 0.00000000e+00],\n",
       "        [1.11022302e-16, 1.00000000e+00]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.I * A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "23bd32db",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1.0000000e+00, 0.0000000e+00],\n",
       "        [8.8817842e-16, 1.0000000e+00]])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A * A.I"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3509019e",
   "metadata": {},
   "source": [
    "数组类型也可以完成类似的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "89a53b06",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 2], [3, 4]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "eab9d269",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a504404a",
   "metadata": {},
   "source": [
    "转置："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "9b50a2c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 3],\n",
       "       [2, 4]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.T"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "411b9f36",
   "metadata": {},
   "source": [
    "其逆矩阵可以用`linalg.inv()`函数计算："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "82bc4036",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.0000000e+00, 0.0000000e+00],\n",
       "       [8.8817842e-16, 1.0000000e+00]])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.dot(linalg.inv(A))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "9a52cc39",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.0000000e+00, 0.0000000e+00],\n",
       "       [8.8817842e-16, 1.0000000e+00]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A @ linalg.inv(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "e871f638",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.00000000e+00, 0.00000000e+00],\n",
       "       [1.11022302e-16, 1.00000000e+00]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.inv(A) @ A"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "250c4d3f",
   "metadata": {},
   "source": [
    "`scipy.linalg`也可以作用在矩阵类型上，返回的还是一个数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0b0ea345",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.matrix([[1, 2], [3, 4]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "fcb3602e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-2. ,  1. ],\n",
       "       [ 1.5, -0.5]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.inv(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9397b1c",
   "metadata": {},
   "source": [
    "矩阵类型的使用比较少，通常都用数组类型替代矩阵类型进行计算。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e297badc",
   "metadata": {},
   "source": [
    "## 线性方程组的求解"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a24b6a4d",
   "metadata": {},
   "source": [
    "考虑下列方程组：\n",
    "```\n",
    " x + 3y + 5z = 10\n",
    "2x + 5y -  z = 8\n",
    "2x + 3y + 8z = 3\n",
    "```\n",
    "\n",
    "矩阵形式为：\n",
    "$$\n",
    "\\left[\n",
    "\\begin{array}{1}\n",
    "1 & 3 & 5 \\\\\n",
    "2 & 5 & -1 \\\\\n",
    "2 & 3 & 8 \\\\\n",
    "\\end{array}\n",
    "\\right]\n",
    "\\left[\n",
    "\\begin{array}{1}\n",
    "x \\\\\n",
    "y \\\\\n",
    "z \\\\\n",
    "\\end{array}\n",
    "\\right]\n",
    "=\n",
    "\\left[\n",
    "\\begin{array}{1}\n",
    "10 \\\\\n",
    "8 \\\\\n",
    "3 \\\\\n",
    "\\end{array}\n",
    "\\right]\n",
    "$$\n",
    "\n",
    "其解为：\n",
    "$$\n",
    "\\left[\n",
    "\\begin{array}{1}\n",
    "x \\\\\n",
    "y \\\\\n",
    "z \\\\\n",
    "\\end{array}\n",
    "\\right]\n",
    "=\n",
    "\\left[\n",
    "\\begin{array}{1}\n",
    "1 & 3 & 5 \\\\\n",
    "2 & 5 & -1 \\\\\n",
    "2 & 3 & 8 \\\\\n",
    "\\end{array}\n",
    "\\right]^{-1}\n",
    "\\left[\n",
    "\\begin{array}{1}\n",
    "10 \\\\\n",
    "8 \\\\\n",
    "3 \\\\\n",
    "\\end{array}\n",
    "\\right]\n",
    "$$\n",
    "\n",
    "故："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "a631aeb7",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 3, 5],\n",
    "              [2, 5, -1],\n",
    "              [2, 3, 8]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "3017b816",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.array([10, 8, 3])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af0e6885",
   "metadata": {},
   "source": [
    "解："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "64da5739",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-8.83870968,  5.25806452,  0.61290323])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.inv(A) @ b"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3ff7b6d3",
   "metadata": {},
   "source": [
    "也可以直接使用`linalg.solve()`函数，直接求解这个方程："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "349caf78",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-8.83870968,  5.25806452,  0.61290323])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.solve(A, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19f5a3b0",
   "metadata": {},
   "source": [
    "## 行列式的计算："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00a11f84",
   "metadata": {},
   "source": [
    "`linalg.det()`函数可以计算矩阵的行列式："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "73f30cf7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-31.000000000000007"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.det(A)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a392795e",
   "metadata": {},
   "source": [
    "行列式非零表示矩阵是可逆的。逆矩阵的行列式与矩阵的行列式满足相乘等于1的关系："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "e2989093",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-0.03225806451612903"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.det(linalg.inv(A))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "7762fa35",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0000000000000002"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.det(linalg.inv(A)) * linalg.det(A)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e46a7a69",
   "metadata": {},
   "source": [
    "## 范数的计算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "9b9bf730",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 2], [3, 4]])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "db9beb30",
   "metadata": {},
   "source": [
    "默认情况下，`linalg.norm()`函数计算的是矩阵的Frobenius范数，该范数计算的是矩阵所有元素平方和的平方根："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "e09c0730",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.477225575051661"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "658a1746",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.477225575051661"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, \"fro\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a0d0a4a5",
   "metadata": {},
   "source": [
    "可以通过`linalg.norm()`函数中的第二个参数，来修改矩阵范数的计算方法。例如，矩阵的1范数，计算的是矩阵中每列元素的和的最大值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "affe6ca1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6.0"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, 1)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "0d8fca3b",
   "metadata": {},
   "source": [
    "矩阵的-1范数，计算的是矩阵中每列元素的和的最小值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "8eed8d80",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.0"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, -1)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "91357c89",
   "metadata": {},
   "source": [
    "矩阵的2范数，计算的是矩阵的最大奇异值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "d0fa7c53",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.464985704219043"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, 2)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b3421820",
   "metadata": {},
   "source": [
    "矩阵的-2范数，计算的是矩阵的最小奇异值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "14389d34",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.36596619062625746"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, -2)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "da8e92f7",
   "metadata": {},
   "source": [
    "矩阵的正无穷范数，计算的是矩阵中每行元素的和的最大值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "18293ca2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7.0"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, np.inf)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6c6ea89e",
   "metadata": {},
   "source": [
    "矩阵的负无穷范数，计算的是矩阵中每行元素的和的最小值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "055a13b9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.0"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(A, -np.inf)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b99a6ae5",
   "metadata": {},
   "source": [
    "`linalg.norm()`函数也可以用来计算向量的范数（也称模）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "5b01a21d",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.array([10, 8, 3])"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a3ffeddd",
   "metadata": {},
   "source": [
    "对于向量来说，linalg.norm()函数默认是向量的2范数，即计算向量元素的平方和的平方根："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "40c8835e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "13.152946437965905"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "0bbce740",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "13.152946437965905"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linalg.norm(b, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e57bf3d",
   "metadata": {},
   "source": [
    "## 特征值分解"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "35edb52d",
   "metadata": {},
   "source": [
    "对于方阵A，特征值λ和特征向量v满足：`Av=λv`。函数`linalg.eig()`可以用来求解特征值和特征向量："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "498f619f",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 2, 3],\n",
    "              [4, 5, 6],\n",
    "              [7, 8, 9]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "4b470fd3",
   "metadata": {},
   "outputs": [],
   "source": [
    "l, v = linalg.eig(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "7695b549",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(A.dot(v), l * v)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a5623725",
   "metadata": {},
   "source": [
    "## 广义逆\n",
    "\n",
    "对于形状为m×n的矩阵A，可以用`linalg.pinv()`求解其广义逆。A的广义逆B满足：`A=ABA`，`B=ABA`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "3e65543f",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 2, 3],\n",
    "              [4, 5, 6]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "f7bc6b49",
   "metadata": {},
   "outputs": [],
   "source": [
    "B = linalg.pinv(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "ac4d5781",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(A, A @ B @ A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "ea20c7e1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(B, B @ A @ B)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7463da00",
   "metadata": {},
   "source": [
    "## 奇异值分解"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "74047d9c",
   "metadata": {},
   "source": [
    "对于形状为m×n的矩阵A，其奇异值分解满足$A=U\\SigmaV^H$，矩阵Σ形状为M×N，主对角线上的元素被称为奇异值。U、V分别为M阶、N阶正交单位矩阵。\n",
    "\n",
    "函数`linalg.svd()`可以对矩阵进行奇异值分解："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "ffae72b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "U, s, Vh = linalg.svd(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "be9437a5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.3863177 , -0.92236578],\n",
       "       [-0.92236578,  0.3863177 ]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "1af28a78",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([9.508032  , 0.77286964])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "b9174266",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.42866713, -0.56630692, -0.7039467 ],\n",
       "       [ 0.80596391,  0.11238241, -0.58119908],\n",
       "       [ 0.40824829, -0.81649658,  0.40824829]])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Vh"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd3bdbca",
   "metadata": {},
   "source": [
    "从奇异值恢复矩阵$\\Sigma$："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "26907656",
   "metadata": {},
   "outputs": [],
   "source": [
    "S = linalg.diagsvd(s, 2, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "c2878f35",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(A, U @ S @ Vh)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd63330a",
   "metadata": {},
   "source": [
    "正交矩阵："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "c0ae03d2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.00000000e+00, -8.49433239e-18],\n",
       "       [-8.49433239e-18,  1.00000000e+00]])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U @ U.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "dec8f9d2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.00000000e+00,  4.13108370e-17,  2.21870637e-17],\n",
       "       [ 4.13108370e-17,  1.00000000e+00, -1.77008767e-16],\n",
       "       [ 2.21870637e-17, -1.77008767e-16,  1.00000000e+00]])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Vh @ Vh.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1d161a1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
